home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Python 1.3.3 / Python 133 PPC / Mac / Lib / test / aete.py < prev    next >
Text File  |  1996-05-19  |  11KB  |  476 lines

  1. # Look for scriptable applications -- that is, applications with an 'aete' resource
  2. # Also contains (partially) reverse engineered 'aete' resource decoding
  3.  
  4. import MacOS
  5. import os
  6. import string
  7. import sys
  8. import types
  9. import StringIO
  10.  
  11. from Res import *
  12.  
  13. def main():
  14.     filename = ""
  15.     redirect(filename, realmain)
  16.  
  17. def redirect(filename, func, *args):
  18.     f = filename and open(filename, 'w')
  19.     save_stdout = sys.stdout
  20.     try:
  21.         if f: sys.stdout = f
  22.         return apply(func, args)
  23.     finally:
  24.         sys.stdout = save_stdout
  25.         if f: f.close()
  26.  
  27. def realmain():
  28.     #list('C:System Folder:Extensions:AppleScript\252')
  29.     #list('C:Tao AppleScript:Finder Liaison:Finder Liaison 1.0')
  30.     list('C:Tao AppleScript:Scriptable Text Editor')
  31.     #list('C:Internet:Eudora 1.4.2:Eudora1.4.2')
  32.     #list('E:Excel 4.0:Microsoft Excel')
  33.     #list('C:Internet:Netscape 1.0N:Netscape 1.0N')
  34.     #find('C:')
  35.     #find('D:')
  36.     #find('E:')
  37.     #find('F:')
  38.  
  39. def find(dir, maxlevel = 5):
  40.     hits = []
  41.     cur = CurResFile()
  42.     names = os.listdir(dir)
  43.     tuples = map(lambda x: (os.path.normcase(x), x), names)
  44.     tuples.sort()
  45.     names = map(lambda (x, y): y, tuples)
  46.     for name in names:
  47.         if name in (os.curdir, os.pardir): continue
  48.         fullname = os.path.join(dir, name)
  49.         if os.path.islink(fullname):
  50.             pass
  51.         if os.path.isdir(fullname):
  52.             if maxlevel > 0:
  53.                 sys.stderr.write("        %s\n" % `fullname`)
  54.                 hits = hits + find(fullname, maxlevel-1)
  55.         else:
  56.             ctor, type = MacOS.GetCreatorAndType(fullname)
  57.             if type in ('APPL', 'FNDR', 'zsys', 'INIT', 'scri', 'cdev'):
  58.                 sys.stderr.write("    %s\n" % `fullname`)
  59.                 try:
  60.                     rf = OpenRFPerm(fullname, 0, '\1')
  61.                 except MacOS.Error, msg:
  62.                     print "Error:", fullname, msg
  63.                     continue
  64.                 UseResFile(rf)
  65.                 n = Count1Resources('aete')
  66.                 if rf <> cur:
  67.                     CloseResFile(rf)
  68.                     UseResFile(cur)
  69.                 if n > 1:
  70.                     hits.append(fullname)
  71.                     sys.stderr.write("YES!  %d in %s\n" % (n, `fullname`))
  72.                     list(fullname)
  73.     return hits
  74.  
  75. def list(fullname):
  76.     cur = CurResFile()
  77.     rf = OpenRFPerm(fullname, 0, '\1')
  78.     try:
  79.         UseResFile(rf)
  80.         resources = []
  81.         for i in range(Count1Resources('aete')):
  82.             res = Get1IndResource('aete', 1+i)
  83.             resources.append(res)
  84.         for i in range(Count1Resources('aeut')):
  85.             res = Get1IndResource('aeut', 1+i)
  86.             resources.append(res)
  87.         print "\nLISTING aete+aeut RESOURCES IN", `fullname`
  88.         for res in resources:
  89.             print "decoding", res.GetResInfo(), "..."
  90.             data = res.data
  91.             try:
  92.                 aete = decode(data)
  93.                 showaete(aete)
  94.                 print "Checking putaete..."
  95.                 f = StringIO.StringIO()
  96.                 putaete(f, aete)
  97.                 newdata = f.getvalue()
  98.                 if len(newdata) == len(data):
  99.                     if newdata == data:
  100.                         print "putaete created identical data"
  101.                     else:
  102.                         newaete = decode(newdata)
  103.                         if newaete == aete:
  104.                             print "putaete created equivalent data"
  105.                         else:
  106.                             print "putaete failed the test:"
  107.                             showaete(newaete)
  108.                 else:
  109.                     print "putaete created different data:"
  110.                     print `newdata`
  111.             except:
  112.                 import traceback
  113.                 traceback.print_exc()
  114.             sys.stdout.flush()
  115.     finally:
  116.         if rf <> cur:
  117.             CloseResFile(rf)
  118.             UseResFile(cur)
  119.  
  120. def decode(data):
  121.     f = StringIO.StringIO(data)
  122.     aete = generic(getaete, f)
  123.     aete = simplify(aete)
  124.     processed = f.tell()
  125.     unprocessed = len(f.read())
  126.     total = f.tell()
  127.     if unprocessed:
  128.         sys.stderr.write("%d processed + %d unprocessed = %d total\n" %
  129.                          (processed, unprocessed, total))
  130.     return aete
  131.  
  132. def simplify(item):
  133.     if type(item) is types.ListType:
  134.         return map(simplify, item)
  135.     elif type(item) == types.TupleType and len(item) == 2:
  136.         return simplify(item[1])
  137.     else:
  138.         return item
  139.  
  140.  
  141. # Here follows the aete resource decoder.
  142. # It is presented bottom-up instead of top-down because there are  direct
  143. # references to the lower-level part-decoders from the high-level part-decoders.
  144.  
  145. def getbyte(f, *args):
  146.     c = f.read(1)
  147.     if not c:
  148.         raise EOFError, 'in getbyte' + str(args)
  149.     return ord(c)
  150.  
  151. def getword(f, *args):
  152.     getalign(f)
  153.     s = f.read(2)
  154.     if len(s) < 2:
  155.         raise EOFError, 'in getword' + str(args)
  156.     return (ord(s[0])<<8) | ord(s[1])
  157.  
  158. def getlong(f, *args):
  159.     getalign(f)
  160.     s = f.read(4)
  161.     if len(s) < 4:
  162.         raise EOFError, 'in getlong' + str(args)
  163.     return (ord(s[0])<<24) | (ord(s[1])<<16) | (ord(s[2])<<8) | ord(s[3])
  164.  
  165. def getostype(f, *args):
  166.     getalign(f)
  167.     s = f.read(4)
  168.     if len(s) < 4:
  169.         raise EOFError, 'in getostype' + str(args)
  170.     return s
  171.  
  172. def getpstr(f, *args):
  173.     c = f.read(1)
  174.     if len(c) < 1:
  175.         raise EOFError, 'in getpstr[1]' + str(args)
  176.     nbytes = ord(c)
  177.     if nbytes == 0: return ''
  178.     s = f.read(nbytes)
  179.     if len(s) < nbytes:
  180.         raise EOFError, 'in getpstr[2]' + str(args)
  181.     return s
  182.  
  183. def getalign(f):
  184.     if f.tell() & 1:
  185.         c = f.read(1)
  186.         ##if c <> '\0':
  187.         ##    print 'align:', `c`
  188.  
  189. def getlist(f, description, getitem):
  190.     count = getword(f)
  191.     list = []
  192.     for i in range(count):
  193.         list.append(generic(getitem, f))
  194.         getalign(f)
  195.     return list
  196.  
  197. def alt_generic(what, f, *args):
  198.     print "generic", `what`, args
  199.     res = vageneric(what, f, args)
  200.     print '->', `res`
  201.     return res
  202.  
  203. def generic(what, f, *args):
  204.     if type(what) == types.FunctionType:
  205.         return apply(what, (f,) + args)
  206.     if type(what) == types.ListType:
  207.         record = []
  208.         for thing in what:
  209.             item = apply(generic, thing[:1] + (f,) + thing[1:])
  210.             record.append((thing[1], item))
  211.         return record
  212.     return "BAD GENERIC ARGS: %s" % `what`
  213.  
  214. getdata = [
  215.     (getostype, "type"),
  216.     (getpstr, "description"),
  217.     (getword, "flags")
  218.     ]
  219. getargument = [
  220.     (getpstr, "name"),
  221.     (getostype, "keyword"),
  222.     (getdata, "what")
  223.     ]
  224. getevent = [
  225.     (getpstr, "name"),
  226.     (getpstr, "description"),
  227.     (getostype, "suite code"),
  228.     (getostype, "event code"),
  229.     (getdata, "returns"),
  230.     (getdata, "accepts"),
  231.     (getlist, "optional arguments", getargument)
  232.     ]
  233. getproperty = [
  234.     (getpstr, "name"),
  235.     (getostype, "code"),
  236.     (getdata, "what")
  237.     ]
  238. getelement = [
  239.     (getostype, "type"),
  240.     (getlist, "keyform", getostype)
  241.     ]
  242. getclass = [
  243.     (getpstr, "name"),
  244.     (getostype, "class code"),
  245.     (getpstr, "description"),
  246.     (getlist, "properties", getproperty),
  247.     (getlist, "elements", getelement)
  248.     ]
  249. getcomparison = [
  250.     (getpstr, "operator name"),
  251.     (getostype, "operator ID"),
  252.     (getpstr, "operator comment"),
  253.     ]
  254. getenumerator = [
  255.     (getpstr, "enumerator name"),
  256.     (getostype, "enumerator ID"),
  257.     (getpstr, "enumerator comment")
  258.     ]
  259. getenumeration = [
  260.     (getostype, "enumeration ID"),
  261.     (getlist, "enumerator", getenumerator)
  262.     ]
  263. getsuite = [
  264.     (getpstr, "suite name"),
  265.     (getpstr, "suite description"),
  266.     (getostype, "suite ID"),
  267.     (getword, "suite level"),
  268.     (getword, "suite version"),
  269.     (getlist, "events", getevent),
  270.     (getlist, "classes", getclass),
  271.     (getlist, "comparisons", getcomparison),
  272.     (getlist, "enumerations", getenumeration)
  273.     ]
  274. getaete = [
  275.     (getword, "major/minor version in BCD"),
  276.     (getword, "language code"),
  277.     (getword, "script code"),
  278.     (getlist, "suites", getsuite)
  279.     ]
  280.  
  281.  
  282. # Display 'aete' resources in a friendly manner.
  283. # This one's done top-down again...
  284.  
  285. def showaete(aete):
  286.     [version, language, script, suites] = aete
  287.     major, minor = divmod(version, 256)
  288.     print "\nVersion %d/%d, language %d, script %d" % \
  289.         (major, minor, language, script)
  290.     for suite in suites:
  291.         showsuite(suite)
  292.  
  293. def showsuite(suite):
  294.     [name, desc, code, level, version, events, classes, comps, enums] = suite
  295.     print "\nSuite %s -- %s (%s)" % (`name`, `desc`, `code`)
  296.     print "Level %d, version %d" % (level, version)
  297.     for event in events:
  298.         showevent(event)
  299.     for cls in classes:
  300.         showclass(cls)
  301.     for comp in comps:
  302.         showcomparison(comp)
  303.     for enum in enums:
  304.         showenumeration(enum)
  305.  
  306. def showevent(event):
  307.     [name, desc, code, subcode, returns, accepts, arguments] = event
  308.     print "\n    Command %s -- %s (%s, %s)" % (`name`, `desc`, `code`, `subcode`)
  309.     print "        returns", showdata(returns)
  310.     print "        accepts", showdata(accepts)
  311.     for arg in arguments:
  312.         showargument(arg)
  313.  
  314. def showargument(arg):
  315.     [name, keyword, what] = arg
  316.     print "        %s (%s)" % (name, `keyword`), showdata(what)
  317.  
  318. def showclass(cls):
  319.     [name, code, desc, properties, elements] = cls
  320.     print "\n    Class %s (%s) -- %s" % (`name`, `code`, `desc`)
  321.     for prop in properties:
  322.         showproperty(prop)
  323.     for elem in elements:
  324.         showelement(elem)
  325.  
  326. def showproperty(prop):
  327.     [name, code, what] = prop
  328.     print "        property %s (%s)" % (`name`, `code`), showdata(what)
  329.  
  330. def showelement(elem):
  331.     [code, keyform] = elem
  332.     print "        element %s" % `code`, "as", keyform
  333.  
  334. def showcomparison(comp):
  335.     [name, code, comment] = comp
  336.     print "    comparison  %s (%s) -- %s" % (`name`, `code`, comment)
  337.  
  338. def showenumeration(enum):
  339.     [code, items] = enum
  340.     print "\n    Enum %s" % `code`
  341.     for item in items:
  342.         showenumerator(item)
  343.  
  344. def showenumerator(item):
  345.     [name, code, desc] = item
  346.     print "        %s (%s) -- %s" % (`name`, `code`, `desc`)
  347.  
  348. def showdata(data):
  349.     [type, description, flags] = data
  350.     return "%s -- %s %s" % (`type`, `description`, showdataflags(flags))
  351.  
  352. dataflagdict = {15: "optional", 14: "list", 13: "enum", 12: "mutable"}
  353. def showdataflags(flags):
  354.     bits = []
  355.     for i in range(16):
  356.         if flags & (1<<i):
  357.             if i in dataflagdict.keys():
  358.                 bits.append(dataflagdict[i])
  359.             else:
  360.                 bits.append(`i`)
  361.     return '[%s]' % string.join(bits)
  362.  
  363.  
  364. # Write an 'aete' resource.
  365. # Closedly modelled after showaete()...
  366.  
  367. def putaete(f, aete):
  368.     [version, language, script, suites] = aete
  369.     putword(f, version)
  370.     putword(f, language)
  371.     putword(f, script)
  372.     putlist(f, suites, putsuite)
  373.  
  374. def putsuite(f, suite):
  375.     [name, desc, code, level, version, events, classes, comps, enums] = suite
  376.     putpstr(f, name)
  377.     putpstr(f, desc)
  378.     putostype(f, code)
  379.     putword(f, level)
  380.     putword(f, version)
  381.     putlist(f, events, putevent)
  382.     putlist(f, classes, putclass)
  383.     putlist(f, comps, putcomparison)
  384.     putlist(f, enums, putenumeration)
  385.  
  386. def putevent(f, event):
  387.     [name, desc, eventclass, eventid, returns, accepts, arguments] = event
  388.     putpstr(f, name)
  389.     putpstr(f, desc)
  390.     putostype(f, eventclass)
  391.     putostype(f, eventid)
  392.     putdata(f, returns)
  393.     putdata(f, accepts)
  394.     putlist(f, arguments, putargument)
  395.  
  396. def putargument(f, arg):
  397.     [name, keyword, what] = arg
  398.     putpstr(f, name)
  399.     putostype(f, keyword)
  400.     putdata(f, what)
  401.  
  402. def putclass(f, cls):
  403.     [name, code, desc, properties, elements] = cls
  404.     putpstr(f, name)
  405.     putostype(f, code)
  406.     putpstr(f, desc)
  407.     putlist(f, properties, putproperty)
  408.     putlist(f, elements, putelement)
  409.  
  410. putproperty = putargument
  411.  
  412. def putelement(f, elem):
  413.     [code, parts] = elem
  414.     putostype(f, code)
  415.     putlist(f, parts, putostype)
  416.  
  417. def putcomparison(f, comp):
  418.     [name, id, comment] = comp
  419.     putpstr(f, name)
  420.     putostype(f, id)
  421.     putpstr(f, comment)
  422.  
  423. def putenumeration(f, enum):
  424.     [code, items] = enum
  425.     putostype(f, code)
  426.     putlist(f, items, putenumerator)
  427.  
  428. def putenumerator(f, item):
  429.     [name, code, desc] = item
  430.     putpstr(f, name)
  431.     putostype(f, code)
  432.     putpstr(f, desc)
  433.  
  434. def putdata(f, data):
  435.     [type, description, flags] = data
  436.     putostype(f, type)
  437.     putpstr(f, description)
  438.     putword(f, flags)
  439.  
  440. def putlist(f, list, putitem):
  441.     putword(f, len(list))
  442.     for item in list:
  443.         putitem(f, item)
  444.         putalign(f)
  445.  
  446. def putalign(f):
  447.     if f.tell() & 1:
  448.         f.write('\0')
  449.  
  450. def putbyte(f, value):
  451.     f.write(chr(value))
  452.  
  453. def putword(f, value):
  454.     putalign(f)
  455.     f.write(chr((value>>8)&0xff))
  456.     f.write(chr(value&0xff))
  457.  
  458. def putostype(f, value):
  459.     putalign(f)
  460.     if type(value) != types.StringType or len(value) != 4:
  461.         raise TypeError, "ostype must be 4-char string"
  462.     f.write(value)
  463.  
  464. def putpstr(f, value):
  465.     if type(value) != types.StringType or len(value) > 255:
  466.         raise TypeError, "pstr must be string <= 255 chars"
  467.     f.write(chr(len(value)) + value)
  468.  
  469.  
  470. # Call the main program
  471.  
  472. if __name__ == '__main__':
  473.     main()
  474. else:
  475.     realmain()
  476.